%{
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>


/*
 * Definiciones de Cantidad Estados
 */

#define CANT_ESTADOS    35
#define CANT_SIMBOLOS   23

#define ESTADO_INICIAL   0

/*
 * Definicion de Mínimos y Máximos.
 */

#define MAX_ID         30
#define MAX_STRING     60
#define MIN_CTE_REAL    1.18e-38   
#define MAX_CTE_REAL    3.40e38 
#define CANT_PALABRAS_RESERVADAS 17
#define MAX_SIMBOLOS   100 
#define LONG_MAX_VAR 30

/******************************Declaracion variables de la TS**************************/

typedef struct{
               int posicion;
               char nombre[LONG_MAX_VAR];
               char tipo[LONG_MAX_VAR];
               char valor[LONG_MAX_VAR];
               int longitud;
               } RegistroTS;

RegistroTS TablaDeSimbolos[MAX_SIMBOLOS];
int CantSimbolos=0;
char CaracterLeido = '\0';
char CaracterAnterior = '\0';
int  yylval = 0;

char Contenido[LONG_MAX_VAR];

int TipoToken = 0;
int Indice = 0;
int Longitud = 0;

int ContComentario1 = 0;
int ContComentario2 = 0;

// Para imprimir la linea y columna de error.
int FilaE = 0;
int ColumnaE = 0;

FILE* ArchFuente;
//FILE* ArchSalida;

char* palabras_reservadas[CANT_PALABRAS_RESERVADAS] =
{ "si", "ssi", "sino", "mientras", "que", "entonces", "inicio", "fin",
    "imprimir", "redondear", "truncar", "entero", "real",
    "texto", "enlista", "declaracion", "findedeclaracion" };
    
    

    

/******************************Fin declaracion variables de la TS**************************/


/******************************Funciones de la TS**************************/

int pilaVar[MAX_SIMBOLOS];
int topeVar=-1;

int BusquedaEnTS(char* Contenido)
{
    int ind;
    for (ind=0;ind<CantSimbolos;ind++)
        if (strcmp(TablaDeSimbolos[ind].nombre,Contenido) == 0)
                 return TablaDeSimbolos[ind].posicion;
    return -1;
}                 

int InsertarEnTS(RegistroTS registro)
{
    registro.posicion = CantSimbolos;
    strcpy(registro.tipo, "  ");
    registro.longitud = Longitud;
    TablaDeSimbolos[CantSimbolos] = registro;
    CantSimbolos++;
    
    return CantSimbolos-1;
}

void GrabarTS()
{
  FILE* TSimbolos;
  TSimbolos = fopen("TablaDeSimbolos.ts", "w");
  
  int ind;
  fprintf(TSimbolos,"%-20s|%-20s|%-20s|%-20s|%-20s\n","POSICION","NOMBRE","TIPO","VALOR","LONGITUD");
  for(ind=0;ind<CantSimbolos;ind++)   
     fprintf(TSimbolos, "%-20d|%-20s|%-20s|%-20s|%-20d\n", TablaDeSimbolos[ind].posicion,TablaDeSimbolos[ind].nombre, TablaDeSimbolos[ind].tipo, TablaDeSimbolos[ind].valor, TablaDeSimbolos[ind].longitud);
  fclose(TSimbolos);   
}     


int apilarVariable (int var)
{
	topeVar++;	
	pilaVar[topeVar]=var;
	
  return var;
}


// desapilarvariable no es utilizada actualmente
int desapilarVariable (int var)
{
	
	var = pilaVar[topeVar];
	topeVar--;	

  return var;
}




void guardarTipos(char* tipo)
{
   while(topeVar != -1)
	{
	  strcpy(TablaDeSimbolos[pilaVar[topeVar]].tipo,tipo );
	  topeVar--;
	}
   
}	
/******************************fin de funciones de la TS**************************/



/************* definiciones y funciones de arbol *************/

// las hojas utilizan int pero los nodos utilizan char* hay que ver como resolverlo
// por ahora asigne dos valores dentro del t_nodo
typedef struct
{

  int dato;
  char* datoChar;
  char* tipo;
  char  tipoNodo;

} t_dato;

typedef struct s_nodo
{
  t_dato datos;
  struct s_nodo *izq;
  struct s_nodo *der;

} t_nodo;

t_nodo * crear_nodo( char* contenido , t_nodo* izq , t_nodo* der )
{
     t_nodo * pNodo = (t_nodo *) malloc( 1 * sizeof(t_nodo) );

     if ( pNodo == NULL )
     {  
        printf("\nError: no es posible asignar memoria para generar el arbol de codigo intermedio.\n");
        exit(1);
     }
    
    pNodo -> datos.tipoNodo = 'n'; 
    pNodo -> datos.datoChar =  contenido;
    pNodo -> datos.dato = -1;
    // asigna el tipo de dato a la estructura de nodo
    // pNodo -> datos.tipo =  paramTipo;

    pNodo-> izq = izq;
    pNodo-> der = der;
  
    return pNodo;
}

t_nodo * crear_hoja( int paramDato  )
{
     t_nodo * pHoja = (t_nodo *) malloc( 1 * sizeof(t_nodo) );

     if ( pHoja == NULL )
     {  
        printf("\nError: no es posible asignar memoria para generar el arbol de codigo intermedio.\n");
        exit(1);
     }
     
     pHoja -> datos.tipoNodo = 'h';
     pHoja -> datos.dato =  paramDato;
     pHoja -> datos.datoChar =  NULL;

      // asigna el tipo de dato a la estructura de nodo
     //pHoja -> datos.tipo =  paramTipo;
     
     pHoja -> izq = pHoja -> der = NULL;
     
    return pHoja;
}

int numPasada = 0;

void mostrar( t_dato * paramDato ) 
{
    
    if(paramDato)
    {
      if ( paramDato->tipoNodo == 'n' )
      {
          int i = 0;
          for( ; i < numPasada; i++) printf("\t");
          printf("Nodo:%-20s  \n", paramDato -> datoChar );
      }
      else
      {
          int i = 0;
          for( ; i< numPasada; i++) printf("\t");
          printf("Hoja: Nombre:%-20s   Valor:%-20s \n", TablaDeSimbolos[ paramDato -> dato ].nombre , TablaDeSimbolos[ paramDato -> dato ].valor );        
      }
    }
    else
      printf("\n DatoChar       Dato      Tipo ");
}

void mostrar_enorden(t_nodo * arbol)
{ 
  numPasada++;
  if( arbol )
  {
    mostrar_enorden(arbol->izq);
    mostrar( &arbol->datos );
    mostrar_enorden(arbol->der);
  }
  numPasada--;
}

void mostrar_preorden(t_nodo * arbol)
{
  numPasada++;
  if( arbol )
  {
    mostrar( &arbol->datos );
    if( arbol->izq ) printf("izq");
    mostrar_preorden(arbol->izq);
    if( arbol->der ) printf("der");
    mostrar_preorden(arbol->der);
  }
  numPasada--;
}

void mostrar_posorden(t_nodo * arbol)
{
  numPasada++;
  if( arbol )
  {
    mostrar_posorden(arbol->izq);
    mostrar_posorden(arbol->der);
    mostrar( &arbol->datos );
  }
  numPasada--;
}


/*
void eliminar_arbol (t_nodo *arbol)
{
  if( arbol )
  {
    arbol_eliminar(arbol->izq);
    arbol_eliminar(arbol->der);
    free(arbol);
  }

}
*/

/************* fin de definiciones y funciones de arbol *************/


/******************* Pilas *******************/


t_nodo* pilaExp[MAX_SIMBOLOS];
int topeExp=-1;
t_nodo* pilaCond[MAX_SIMBOLOS];
int topeCond=-1;
t_nodo* pilaSent[MAX_SIMBOLOS];
int topeSent=-1;



t_nodo* apilarExpresion (t_nodo * exp)
{
	topeExp++;	
	pilaExp[topeExp]=exp;

  return pilaExp[topeExp];
	
}

t_nodo* desapilarExpresion(t_nodo * exp)
{

     exp=pilaExp[topeExp];
     topeExp--;	
   
     return exp;
}

t_nodo* apilarCondicion (t_nodo * cond)
{
	topeCond++;	
	pilaCond[topeCond]=cond;

  return pilaCond[topeCond];
	
}

t_nodo* desapilarCondicion(t_nodo * cond)
{

     cond = pilaCond[ topeCond ];
     topeCond--;	
    
     return cond;
   
}

t_nodo* apilarSentencia (t_nodo * sent)
{
	topeSent++;	
	pilaSent[topeSent]= sent;
  
  return pilaSent[topeSent];
	
}

t_nodo* desapilarSentencia(t_nodo* sent)
{

     sent=pilaSent[topeSent];
     topeSent--;	
   
     return sent;
}   	

t_nodo *  Pcondiciones,
       *  Plista_sentencias,
       *  Psentencia, 
       *  Pconstantes,
       *  Pexpresion,
       *  Pcondicion,
       *  Ptermino,
       *  Pimprimir,
       *  Pfactor,
       *  Ptruncar,
       *  Predondear, 
       *  Pcadena_id, 
       *  Pdecision_ssi,  
       *  Pdecision,
       *  Piteracion, 
       *	Pasignacion, 
       *  Pprograma,
       *  PenLista;

/************** Fin de Pilas *****************/

void llenarArbol(void)
{
    t_nodo * aux, * Pposicion;

    Pposicion = Pprograma;

    while (  topeSent >= 0  )
    {
        Pposicion ->der = desapilarSentencia( aux );
        Pposicion = Pposicion -> der;

        topeSent--;
    }
}

%}

%%

%token ID;
%token CTE_NUM;
%token CTE_REAL;
%token CTE_STRING;
%token DECLARACION;
%token FINDEDECLARACION;
%token SI;
%token ENTONCES;
%token INICIO;
%token FIN ;
%token SINO;
%token ENLISTA;
%token SSI;
%token MIENTRAS;
%token QUE;
%token TRUNCAR;
%token REDONDEAR;
%token IMPRIMIR;
%token ENTERO;
%token REAL;
%token TEXTO;		
%token COMA;
%token DOS_PUNTOS;
%token FIN_DE_LINEA;
%token OP_COMP;
%token OP_ASIG;
%token OP_MENOR_IG;
%token OP_MENOR;
%token OP_MAYOR_IG;
%token OP_MAYOR;
%token OP_SUMA;
%token OP_RESTA;
%token OP_MULT;
%token OP_DIV;
%token OP_AND;
%token OP_OR;
%token OP_DIST;
%token OP_NEG;
%token PAR_ABRE;
%token PAR_CIERRA;
%token CORCH_ABRE;
%token CORCH_CIERRA;
%start programa_principal; 
     


programa_principal : programa {printf("\n===================== \n  Compilacion Exitosa\n=====================\nARBOL: \n"); mostrar_preorden( Pprograma ); printf("\n\n"); } ;

programa : INICIO lista_sentencias FIN { Pprograma = crear_nodo ( "Programa"   , NULL , NULL ); llenarArbol() ;printf("solo lista_sentencias \n"); } 
        | declaracion INICIO lista_sentencias FIN { Pprograma = crear_nodo ( "Programa"   , NULL , NULL ); llenarArbol() ;printf("solo lista_sentencias \n"); ;}                     

declaracion : DECLARACION lista_variables FINDEDECLARACION { GrabarTS(); printf("Declaracion \n "); } ;

lista_variables : variable { printf("Variable \n "); } 
		| lista_variables variable { printf("Variables declaradas \n "); } ; 

variable : ENTERO DOS_PUNTOS lista_id FIN_DE_LINEA { guardarTipos("ENTERO");printf("Hay enteros \n "); }  
		| REAL DOS_PUNTOS lista_id FIN_DE_LINEA { guardarTipos("REAL");printf("Hay reales \n "); } 
		| TEXTO DOS_PUNTOS lista_id FIN_DE_LINEA { guardarTipos("TEXTO");printf("Hay texto \n "); } ;

lista_id : ID { apilarVariable($1);}
	     | lista_id COMA ID { apilarVariable($3);};

lista_sentencias : sentencia  { Plista_sentencias = apilarSentencia( Psentencia ); printf("Tengo sentencia \n "); } 
                 | lista_sentencias sentencia { Plista_sentencias = apilarSentencia( Psentencia ); printf("Tengo sentencias \n "); } ;

sentencia : decision { Psentencia =  Pdecision; printf("Tengo si\n "); } 

            | iteracion { Psentencia = Piteracion; printf("Tengo mientras que \n "); } 

            | imprimir FIN_DE_LINEA { Psentencia = Pimprimir; printf("Tengo imprimir \n "); } 

            | asignacion FIN_DE_LINEA { Psentencia = Pasignacion; printf("Tengo asignacion \n "); } ;

decision  : SI PAR_ABRE condiciones PAR_CIERRA ENTONCES INICIO lista_sentencias FIN { Pdecision = crear_nodo("si",Pcondiciones, desapilarSentencia( Plista_sentencias ));printf("SI\n");}
	       // Hay que verificar donde queda el nodo de sentencias verdaderas y falsas, para saber como tranformarlo al asm
          | SI PAR_ABRE condiciones PAR_CIERRA ENTONCES INICIO lista_sentencias FIN SINO INICIO lista_sentencias FIN { Pdecision= crear_nodo("si",Pcondiciones,crear_nodo("cuerpo",desapilarSentencia(Plista_sentencias),desapilarSentencia(Plista_sentencias))) ;printf("SI con SINO\n");} ;

condiciones : condicion {Pcondiciones= Pcondicion; printf("Condicion Simple\n");}
		| condicion OP_AND condicion { Pcondiciones= crear_nodo( "AND", desapilarCondicion(Pcondicion), desapilarCondicion(Pcondicion) )  ;printf("Condicion AND\n");}
		| condicion OP_OR condicion {Pcondiciones= crear_nodo( "AND", desapilarCondicion(Pcondicion), desapilarCondicion(Pcondicion) )  ;printf("Condicion OR\n");} ;

condiciones : OP_NEG PAR_ABRE condicion PAR_CIERRA {Pcondiciones=crear_nodo("!",desapilarCondicion(Pcondicion),NULL);printf("Condicion NEG\n");} ;

condicion : expresion OP_MAYOR expresion {  apilarCondicion( Pcondicion = crear_nodo(">",desapilarExpresion(Pexpresion), desapilarExpresion(Pexpresion) ));printf("Condicion Mayor\n");}
		| expresion OP_MAYOR_IG expresion {  apilarCondicion( Pcondicion = crear_nodo(">=",desapilarExpresion(Pexpresion),desapilarExpresion(Pexpresion)));printf("Condicion Mayor Igual\n");}
		| expresion OP_MENOR expresion {  apilarCondicion( Pcondicion = crear_nodo("<",desapilarExpresion(Pexpresion),desapilarExpresion(Pexpresion)));printf("Condicion Menor\n");}
		| expresion OP_MENOR_IG expresion {  apilarCondicion( Pcondicion =  crear_nodo("<=",desapilarExpresion(Pexpresion),desapilarExpresion(Pexpresion)));printf("Condicion Menor Igual\n");}
		| expresion OP_COMP expresion {  apilarCondicion( Pcondicion = crear_nodo("==",desapilarExpresion(Pexpresion),desapilarExpresion(Pexpresion)));printf("Condicion Comparacion\n");}
		| expresion OP_DIST expresion {   apilarCondicion( Pcondicion = crear_nodo("!=",desapilarExpresion(Pexpresion),desapilarExpresion(Pexpresion)));printf("Condicion Op Distinto\n");} ;

condicion : ENLISTA PAR_ABRE ID FIN_DE_LINEA CORCH_ABRE constantes CORCH_CIERRA PAR_CIERRA {PenLista=crear_nodo( "ENLISTA", Pconstantes , desapilarExpresion( Pexpresion  ) )  ;printf("ENLISTA\n");} ;

expresion : termino {Pexpresion= apilarExpresion(Ptermino);printf("Termino\n");}
		| expresion OP_SUMA termino { apilarExpresion(crear_nodo("+",desapilarExpresion(Pexpresion),Ptermino)) ; printf("Suma\n"); }
		| expresion OP_RESTA termino  {apilarExpresion(crear_nodo("-",desapilarExpresion(Pexpresion),Ptermino)) ; printf("Resta\n"); } ;

termino : factor {Ptermino=Pfactor;printf("Factor\n");}
	   | termino OP_MULT factor {Ptermino= crear_nodo("*",Ptermino,Pfactor);printf("Multiplicacion\n");}
	   | termino OP_DIV factor {Ptermino= crear_nodo("/",Ptermino,Pfactor) ;printf("Division\n");} ;

factor : PAR_ABRE expresion PAR_CIERRA {Pfactor=desapilarExpresion(Pexpresion);printf("Expr entre parentesis\n");}
         | ID {Pfactor=crear_hoja($1);printf("ID\n"); }
         | CTE {Pfactor=crear_hoja($1);printf("CTE\n"); }
	   | decision_ssi {Pfactor=Pdecision_ssi;printf("SSI\n"); }
	   | redondear {Pfactor=Predondear;printf("Redondear\n"); }
	   | truncar {Pfactor=Ptruncar;printf("Truncar\n"); } ;

decision_ssi :  SSI PAR_ABRE condiciones COMA expresion COMA expresion PAR_CIERRA {Pdecision_ssi=crear_nodo("ssi",Pcondiciones,crear_nodo("cuerpo",desapilarExpresion(Pexpresion),desapilarExpresion(Pexpresion) ) );printf("SSI\n");} ;

iteracion : MIENTRAS QUE PAR_ABRE condiciones PAR_CIERRA ENTONCES INICIO lista_sentencias FIN  {Piteracion=crear_nodo("MIENTRAS",Pcondiciones,Plista_sentencias);printf("Iteracion\n");} ;

asignacion : cadena_id expresion {Pasignacion=crear_nodo("=",Pcadena_id,desapilarExpresion(Pexpresion));printf("Asignacion\n");} ;

cadena_id : ID OP_ASIG {Pcadena_id=crear_hoja($1);printf("cadena_id\n");}
		| cadena_id ID OP_ASIG {Pcadena_id=crear_nodo("=",Pcadena_id,crear_hoja($2));printf("cadena_id + =\n");} ;

truncar : TRUNCAR PAR_ABRE expresion PAR_CIERRA {Ptruncar=crear_nodo("truncar",desapilarExpresion(Pexpresion),NULL);printf("truncar\n");}  ;

redondear : REDONDEAR PAR_ABRE expresion PAR_CIERRA {Predondear=crear_nodo("redondear",desapilarExpresion(Pexpresion),NULL);printf("redondear\n");} ;

imprimir : IMPRIMIR PAR_ABRE expresion PAR_CIERRA {Pimprimir=crear_nodo("imprimir",desapilarExpresion(Pexpresion),NULL);printf("imprimir\n");} ;


constantes : CTE { Pconstantes = crear_hoja( $1 ); printf("CONSTANTE\n"); } 
           | constantes FIN_DE_LINEA CTE { Pconstantes = crear_nodo("constantes", crear_hoja($3) ,Pconstantes ) ; printf("Muchas Ctes.\n"); } ;


CTE :  CTE_NUM {strcpy(TablaDeSimbolos[$1].tipo,"ENTERO" );printf("CTE\n");} | CTE_REAL {strcpy(TablaDeSimbolos[$1].tipo,"REAL" );printf("CTE\n")}| CTE_STRING {strcpy(TablaDeSimbolos[$1].tipo,"TEXTO" );printf("CTE\n");} 

%%



int yyerror (char *s) {
    fprintf( stderr , "%s: En fila %d, columna %d\n",s , FilaE, ColumnaE);
}


int getEvento(char c)
{
  int ret = -1;

  /* Verifico si 'c' esta en el rango [A-Za-z] y devuelvo la columna 0 */
  if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
  {
    ret = 0;

    /* Verifico si 'c' esta en el rango [0-9] y devuelvo la columna 1 */
  }
  else if (c >= '0' && c <= '9')
  {

    ret = 1;

  }
  else
  {

    switch (c)
    {
    /**/
    case '.':
      ret = 2;
      break;
    case '@':
      ret = 3;
      break;
    case '=':
      ret = 4;
      break;
    case '<':
      ret = 5;
      break;
    case '>':
      ret = 6;
      break;
    case '+':
      ret = 7;
      break;
    case '-':
      ret = 8;
      break;
    case '*':
      ret = 9;
      break;
    case '/':
      ret = 10;
      break;
    case '(':
      ret = 11;
      break;
    case ')':
      ret = 12;
      break;
    case '\"':
      ret = 13;
      break;
    case '!':
      ret = 14;
      break;
    case '&':
      ret = 15;
      break;
    case '|':
      ret = 16;
      break;
    case ',':
      ret = 17;
      break;
    case ':':
      ret = 18;
      break;
    case '[':
      ret = 19;
      break;
    case ']':
      ret = 20;
      break;
    case ';':
      ret = 21;
      break;
    case '\n':
      ret = 22;
      break;
    case ' ':
      ret = 22;
      break;
    case '\t':
      ret = 22;
      break;
    case '\0':
      ret = 22;
      break;
    
    case EOF:
    break;

    default:
      printf("Caracter no reconocido: '%c'\n", c);

    }

  }

  return ret;
}

char* strlwr( char* s )
{
  char* p = s;
  while (*p = tolower( *p )) p++;
  return s;
}

char* strupper( char* s )
{
  char* p = s;
  while (*p = toupper( *p )) p++;
  return s;
}

void Inic_id()
{
  Indice = 0;
  memset(Contenido, '\0', sizeof(Contenido));
  Contenido[Indice++] = CaracterLeido;

  Longitud = 1;
}

void Cont_id()
{
  Contenido[Indice++] = CaracterLeido;
  Longitud++;

  if (Longitud > MAX_ID)
  {
    printf("\n Error, Nombre de identificador mayor a %d caracteres \n",
        MAX_ID );
    exit(1);
  }

}

void Fin_id()
{

  int palabra_reservada;  
  palabra_reservada = es_palabra_reservada();

  if ( palabra_reservada != -1 )
  {
    switch ( palabra_reservada )
    {
        case 0:
                TipoToken = SI;
                break;

        case 1:
                 TipoToken = SSI;
                 break;

        case 2:
                TipoToken = SINO;
                break;

        case 3:
                TipoToken = MIENTRAS;
                break;

        case 4:
                TipoToken = QUE;
                break;

        case 5:
                TipoToken = ENTONCES;
                break;

        case 6:
                TipoToken = INICIO;
                break;

        case 7:
                TipoToken = FIN;
                break;

        case 8:
                TipoToken = IMPRIMIR;
                break;

        case 9:
                TipoToken = REDONDEAR;
                break;

        case 10:
                TipoToken = TRUNCAR;
                break;

        case 11:
                TipoToken = ENTERO;
                break;

        case 12:
                TipoToken = REAL;
                break;

        case 13:
                TipoToken = TEXTO;
                break;

        case 14:
                TipoToken = ENLISTA;
                break;

        case 15:
                TipoToken = DECLARACION;
                break;

        case 16:
                TipoToken = FINDEDECLARACION;
                break;
    }

  

  }
  else
  {
    TipoToken = ID;

    //   llenar o agregar datos a la tabla de simbolos

    if((yylval = BusquedaEnTS(Contenido)) == -1)
         {
            RegistroTS registro;
            strcpy(registro.nombre, Contenido);
            strcpy(registro.valor, "  ");
            yylval = InsertarEnTS(registro);
         }


  }
}

void Inic_cte_num()
{
  Indice = 0;
  memset(Contenido, '\0', sizeof(Contenido));
  Contenido[Indice++] = CaracterLeido;
}

void Cont_cte_num()
{
  Contenido[Indice++] = CaracterLeido;
}

void Fin_cte_num()
{
  TipoToken = CTE_NUM;

  if (atof(Contenido) == HUGE_VAL || atof(Contenido) > MAX_CTE_REAL)
  {
    printf("\n Error, constante númerica entera menor al minimo representable:  %s \n", Contenido);
    exit(1);
  }

  if (atof(Contenido) == HUGE_VAL || atof(Contenido) < MIN_CTE_REAL) // VER ATOF: if(atof(token) != 0 && atof(token) < MIN_CTE_REAL) nose porque hace esto
  {
    printf("\n Error, constante númerica entera menor al minimo representable:  %s \n" , Contenido);
    exit(1);
  }

  //    llenar o agregar datos a la tabla de simbolos

    if((yylval = BusquedaEnTS(Contenido)) == -1)
     {
        RegistroTS registro;
        strcpy(registro.nombre, Contenido);
        strcpy(registro.valor, strcat(Contenido,".00"));
        yylval = InsertarEnTS(registro);
     }

}

void Inic_cte_real()
{
  Indice = 0;
  memset(Contenido, '\0', sizeof(Contenido));
  Contenido[Indice++] = CaracterLeido;
}

void Cont_cte_real()
{
  Contenido[Indice++] = CaracterLeido;
}

void Fin_cte_real()
{
  TipoToken = CTE_REAL;

  if (atof(Contenido) == HUGE_VAL || atof(Contenido) > MAX_CTE_REAL)
  {
    printf("\n Error, constante númerica real mayor al maximo representable:  %s \n", Contenido);
    exit(1);
  }

  if (atof(Contenido) == HUGE_VAL || atof(Contenido) < MIN_CTE_REAL) // VER ATOF: if(atof(token) != 0 && atof(token) < MIN_CTE_REAL) nose porque hace esto
  {
    printf("\n Error, constante númerica real menor al minimo representable:   %s \n" , Contenido);
    exit(1);
  }

  //    llenar o agregar datos a la tabla de simbolos

  if((yylval = BusquedaEnTS(Contenido)) == -1)
    {
        RegistroTS registro;
        strcpy(registro.nombre, Contenido);
        strcpy(registro.valor,strcat(Contenido,"0"));//le agrego un 0 por las dudas que termine en punto
        yylval = InsertarEnTS(registro);
    }
}



void Inic_fin_linea()
{
  Indice = 0;
  memset(Contenido, '\0', sizeof(Contenido));
  Contenido[Indice++] = CaracterLeido;
}

void Fin_linea()
{
  TipoToken = FIN_DE_LINEA;
}

void Inic_op_comp()
{
  Indice = 0;
  memset(Contenido, '\0', sizeof(Contenido));
  Contenido[Indice++] = CaracterLeido;
}

void Cont_op_comp()
{
  Contenido[Indice++] = CaracterLeido;
}

void Fin_op_comp()
{
  TipoToken = OP_COMP;
}

void Fin_op_asig()
{
  TipoToken = OP_ASIG;
}

void Inic_op_menor_ig()
{
  Indice = 0;
  memset(Contenido, '\0', sizeof(Contenido));
  Contenido[Indice++] = CaracterLeido;
}

void Cont_op_menor_ig()
{
  Contenido[Indice++] = CaracterLeido;
}

void Fin_op_menor_ig()
{
  TipoToken = OP_MENOR_IG;
}

void Fin_op_menor()
{
  TipoToken = OP_MENOR;
}

void Inic_op_mayor_ig()
{
  Indice = 0;
  memset(Contenido, '\0', sizeof(Contenido));
  Contenido[Indice++] = CaracterLeido;
}

void Cont_op_mayor_ig()
{
  Contenido[Indice++] = CaracterLeido;
}

void Fin_op_mayor_ig()
{
  TipoToken = OP_MAYOR_IG;
}

void Fin_op_mayor()
{
  TipoToken = OP_MAYOR;
}

void Inic_op_suma()
{
  Indice = 0;
  memset(Contenido, '\0', sizeof(Contenido));
  Contenido[Indice++] = CaracterLeido;
}

void Fin_op_suma()
{
  TipoToken = OP_SUMA;
}

void Inic_op_resta()
{
  Indice = 0;
  memset(Contenido, '\0', sizeof(Contenido));
  Contenido[Indice++] = CaracterLeido;
}

void Fin_op_resta()
{
  TipoToken = OP_RESTA;
}

void Inic_op_mult()
{
  Indice = 0;
  memset(Contenido, '\0', sizeof(Contenido));
  Contenido[Indice++] = CaracterLeido;
}

void Fin_op_mult()
{
  TipoToken = OP_MULT;
}

void Inic_op_div()
{
  Indice = 0;
  memset(Contenido, '\0', sizeof(Contenido));
  Contenido[Indice++] = CaracterLeido;
}

void Fin_op_div()
{
  TipoToken = OP_DIV;
}

int es_palabra_reservada()
{
  int i = 0 , numPalabraReservada = -1;

  while( numPalabraReservada == -1  && i < CANT_PALABRAS_RESERVADAS )
  {
    if ( strcmp( (char *) strlwr(Contenido), palabras_reservadas[i]) == 0 )
    {    
        numPalabraReservada = i; 
    }

    i++;
  }

  return numPalabraReservada;
}

void Inic_para()
{
  memset(Contenido, '\0', sizeof(Contenido));
  Indice = 0;
  Contenido[Indice++] = CaracterLeido;
}

void Fin_para()
{
  TipoToken = PAR_ABRE;
}

void Inic_parc()
{
  memset(Contenido, '\0', sizeof(Contenido));
  Indice = 0;
  Contenido[Indice++] = CaracterLeido;
}

void Fin_parc()
{
  TipoToken = PAR_CIERRA;
}

void Inic_corcha()
{
  memset(Contenido, '\0', sizeof(Contenido));
  Indice = 0;
  Contenido[Indice++] = CaracterLeido;
}

void Fin_corcha()
{
  TipoToken = CORCH_ABRE;
}

void Inic_corchc()
{
  memset(Contenido, '\0', sizeof(Contenido));
  Indice = 0;
  Contenido[Indice++] = CaracterLeido;
}

void Fin_corchc()
{
  TipoToken = CORCH_CIERRA;
}

void Inic_op_and()
{
  memset(Contenido, '\0', sizeof(Contenido));
  Indice = 0;
  Contenido[Indice++] = CaracterLeido;
}

void Cont_op_and()
{
  Contenido[Indice++] = CaracterLeido;
}

void Fin_op_and()
{
  TipoToken = OP_AND;
}

void Inic_op_or()
{
  memset(Contenido, '\0', sizeof(Contenido));
  Indice = 0;
  Contenido[Indice++] = CaracterLeido;
}

void Cont_op_or()
{
  Contenido[Indice++] = CaracterLeido;
}

void Fin_op_or()
{
  TipoToken = OP_OR;
}

void Inic_coma()
{
  memset(Contenido, '\0', sizeof(Contenido));
  Indice = 0;
  Contenido[Indice++] = CaracterLeido;
}

void Fin_coma()
{
  TipoToken = COMA;
}

void Inic_cte_string()
{
  memset(Contenido, '\0', sizeof(Contenido));
  Indice = 0;
  Longitud = 0;
}

void Cont_cte_string()
{
  if (CaracterLeido != '"')
  {
    Contenido[Indice++] = CaracterLeido;
    Longitud++;
  }
}

void Fin_cte_string()
{
  TipoToken = CTE_STRING;
  if (Longitud > MAX_STRING)
  {
    printf("\n Error, constante string mayor a %d caracteres\n", MAX_STRING);
    exit(1);
  }
  
    if((yylval = BusquedaEnTS(Contenido)) == -1)
    {
        RegistroTS registro;
        strcpy(registro.nombre, Contenido);
        strcpy(registro.valor, Contenido);
        yylval = InsertarEnTS(registro);
    }

}

void Inic_op_dist()
{
  memset(Contenido, '\0', sizeof(Contenido));
  Indice = 0;
  Contenido[Indice++] = CaracterLeido;
}

void Cont_op_dist()
{
  Contenido[Indice++] = CaracterLeido;
}

void Fin_op_dist()
{
  TipoToken = OP_DIST;
}

void Inic_op_neg()
{
  memset(Contenido, '\0', sizeof(Contenido));
  Indice = 0;
  Contenido[Indice++] = CaracterLeido;
}

void Fin_op_neg()
{
  TipoToken = OP_NEG;
}

void Fin_dospuntos()
{
  TipoToken = DOS_PUNTOS;
}

void Comentario1()
{
  if (CaracterAnterior == ':' && CaracterLeido == '@')
    ContComentario1++;

  if (CaracterAnterior == '@' && CaracterLeido == ':')
    ContComentario1--;

  if (ContComentario1 > 0 && CaracterLeido == EOF)
  {
    printf(
        "Error, EOF dentro del primer nivel de comentario, comentario no balanceado \n");
    exit(1);
  }
}

void Comentario2()
{
  if (CaracterAnterior == ':' && CaracterLeido == '@')
    ContComentario2 = 1;

  if (CaracterAnterior == '@' && CaracterLeido == ':')
    ContComentario2--;

  if (ContComentario2 > 0 && CaracterLeido == EOF)
  {
    printf(
        "Error, EOF dentro del segundo nivel de comentario, comentario no balanceado \n");
    exit(1);
  }
}

void Error()
{

  printf("Error lexico \n");
  exit(1);
}

void Salta_caracter()
{
}


 
int NuevoEstado [CANT_ESTADOS][CANT_SIMBOLOS] =  {
 {1, 2, 34, -1, 5, 7, 9, 11, 12, 13, 14, 15, 16, 17, 19, 21, 23, 25, 26, 32, 33, 4, 0} ,
 {1, 1, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 2, 3, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 3, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 6, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 8, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 10, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 17, 17, 17, 17, 17, 17, 17, 17, 17} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 20, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1, -1} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 27, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {27, 27, 27, 28, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 29, 27, 27, 27, 27} ,
 {27, 27, 27, 28, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 27, 27, 27, 27} ,
 {27, 27, 27, 30, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 29, 27, 27, 27, 27} ,
 {30, 30, 30, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30} ,
 {30, 30, 30, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 27, 30, 30, 30, 30} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35} ,
 {-1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1} 
 };

void (*Procesos[CANT_ESTADOS][CANT_SIMBOLOS])() = { 
{Inic_id,Inic_cte_num,Inic_cte_real,Error,Inic_op_comp,Inic_op_menor_ig,Inic_op_mayor_ig,Inic_op_suma,Inic_op_resta,Inic_op_mult,Inic_op_div,Inic_para,Inic_parc,Inic_cte_string,Inic_op_dist,Inic_op_and,Inic_op_or,Inic_coma,Comentario1,Inic_corcha,Inic_corchc,Inic_fin_linea,Salta_caracter} ,  {Cont_id,Cont_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id,Fin_id} ,  {Fin_cte_num,Cont_cte_num,Cont_cte_real,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num,Fin_cte_num} ,  {Fin_cte_real,Cont_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real,Fin_cte_real} ,  {Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea,Fin_linea} ,  {Fin_op_asig,Fin_op_asig,Fin_op_asig,Fin_op_asig,Cont_op_comp,Fin_op_asig,Fin_op_asig,Fin_op_asig,Fin_op_asig,Fin_op_asig,Fin_op_asig,Fin_op_asig,Fin_op_asig,Fin_op_asig,Fin_op_asig,Fin_op_asig,Fin_op_asig,Fin_op_asig,Fin_op_asig,Fin_op_asig,Fin_op_asig,Fin_op_asig,Fin_op_asig} ,  {Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp,Fin_op_comp} ,  {Fin_op_menor,Fin_op_menor,Fin_op_menor,Fin_op_menor,Cont_op_menor_ig,Fin_op_menor,Fin_op_menor,Fin_op_menor,Fin_op_menor,Fin_op_menor,Fin_op_menor,Fin_op_menor,Fin_op_menor,Fin_op_menor,Fin_op_menor,Fin_op_menor,Fin_op_menor,Fin_op_menor,Fin_op_menor,Fin_op_menor,Fin_op_menor,Fin_op_menor,Fin_op_menor} ,  {Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig,Fin_op_menor_ig} ,  {Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Cont_op_mayor_ig,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor,Fin_op_mayor} ,  {Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig,Fin_op_mayor_ig} ,  {Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma,Fin_op_suma} ,  {Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta,Fin_op_resta} ,  {Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult,Fin_op_mult} ,  {Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div,Fin_op_div} ,  {Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para,Fin_para} ,  {Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc,Fin_parc} ,  {Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string,Cont_cte_string} ,  {Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string,Fin_cte_string} ,  {Fin_op_neg,Fin_op_neg,Fin_op_neg,Fin_op_neg,Cont_op_dist,Fin_op_neg,Fin_op_neg,Fin_op_neg,Fin_op_neg,Fin_op_neg,Fin_op_neg,Fin_op_neg,Fin_op_neg,Fin_op_neg,Fin_op_neg,Fin_op_neg,Fin_op_neg,Fin_op_neg,Fin_op_neg,Fin_op_neg,Fin_op_neg,Fin_op_neg,Fin_op_neg} ,  {Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist,Fin_op_dist} ,  {Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Cont_op_and,Error,Error,Error,Error,Error,Error,Error} ,  {Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and,Fin_op_and} ,  {Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Cont_op_or,Error,Error,Error,Error,Error,Error} ,  {Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or,Fin_op_or} ,  {Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma,Fin_coma} ,  {Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Comentario1,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos,Fin_dospuntos} ,  {Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario2,Comentario1,Comentario1,Comentario1,Comentario1} ,  {Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1} ,  {Comentario1,Comentario1,Comentario1,Comentario2,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario1,Comentario2,Comentario1,Comentario1,Comentario1,Comentario1} ,  {Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2} ,  {Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario2,Comentario1,Comentario2,Comentario2,Comentario2,Comentario2} ,  {Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha,Fin_corcha} ,  {Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc,Fin_corchc} ,  {Error,Cont_cte_real,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error,Error}
};


int yylex()
{
  int estado = ESTADO_INICIAL;
  int estadoFinal = CANT_ESTADOS;
  int columna = 0;

  if ( CaracterLeido == EOF ){
        TipoToken = 0;
        estado = estadoFinal;
  }

  while (estado != estadoFinal)
  {

    // contabilizo filas y columnas leidas para informar errores
    if ( CaracterLeido != '\n' ) 
    {
      ColumnaE++;
      //printf("%c", CaracterLeido);
    }
    else
    {
      FilaE++;
      ColumnaE = 0;
      //printf("%c", CaracterLeido);
    }

    /*Obtengo la columna de la matriz*/
    columna = getEvento(CaracterLeido);

    if (columna >= 0)
    {
      /*Ejecuto la función correspondiente*/
      (*Procesos[estado][columna] )();

      estado = NuevoEstado[estado][columna];

      if ( estado != estadoFinal ){
        CaracterAnterior = CaracterLeido;
        CaracterLeido = (char) getc(ArchFuente);
      }
       

    }
    else
    {
      if ( feof(ArchFuente) )
        TipoToken = 0;
      else
        TipoToken = -1;
      
      estado = estadoFinal;
    }

  }

  return TipoToken;

}


int main(int argc, char *argv[])
{
  int tipoToken = 0;

  printf("Abriendo Archivo %s...", argv[1]);

  /*Apertura de Archivo codigo fuente*/
  ArchFuente = fopen(argv[1], "r");

  if (ArchFuente != NULL)
  {
    /*Confirmo que el archivo se abrio bien.*/
    printf("[OK]\n");

    //CaracterLeido = CaracterAnterior = getc(ArchFuente);
    
    if ( !feof( ArchFuente ) )
      yyparse();

  }
  else
  {
    printf("[MAL]\n");
    printf("Error de apertura de archivo.\n");
  }

  if (TipoToken == -1)
  {
    printf("***************Error Léxico***************\n");
  }

  GrabarTS();

  /* Cierre de Archivos */

  printf("Cerrando archivo entrada...");
  fclose(ArchFuente);
  printf("[OK]\n");

  return 0;
}





